#include <iostream>
#include <bitset>
#include <string>
#include <sstream>
#include <fstream>
#include "PermutationsUnitTests.h"
#include "Permutations.h"
#include "Permutation.h"
#include "Chain.h"

using std::string;
using std::bitset;
using std::fstream;

// Check Intersection: count the intersection between 2 int arrays and check intersection removal
TestUtils::TestResult CheckIntersection1() 
{
	VERTEX_SIZE arrayA[11] = {0,1,2,3,4,5,6,7,8,9,10};
	VERTEX_SIZE arrayB[11] = {10,9,8,7,6,5,4,3,2,1,11};
	//simple intersection: 10
	Permutation* per = new Permutation(arrayA, 4,11);
	int intersection = per->CountIntersection(arrayB, 11);
	if (TestUtils::VerifyIsTrue(intersection == 10,"Did not get right intersection size") != TestUtils::TestPassed)
	{
		return TestUtils::TestFailed;
	}

	VERTEX_SIZE *noIntersection = Permutation::GetMatrixWithoutIntersection(arrayA, 11, arrayB, 11,10);
	if (TestUtils::VerifyIsTrue(noIntersection[0] == 0,"Did not clean matrix correctly") != TestUtils::TestPassed)
	{
		return TestUtils::TestFailed;
	}

	return TestUtils::TestPassed;

}

// Check Intersection: count the intersection between 2 int arrays and check intersection removal
TestUtils::TestResult CheckIntersection2() 
{
	VERTEX_SIZE arrayA[6] = {13,54,555,100000000,16,77};
	VERTEX_SIZE arrayB[6] = {10,1111111111,43,90,77,78};
	//simple intersection: 1
	Permutation* per = new Permutation(arrayA,32,6);
	int intersection = per->CountIntersection(arrayB,6);
	if (TestUtils::VerifyIsTrue(intersection == 1,"Did not get right intersection size")!= TestUtils::TestPassed)
	{
		return TestUtils::TestFailed;
	}
	
	VERTEX_SIZE *noIntersection = Permutation::GetMatrixWithoutIntersection(arrayA, 6, arrayB, 6,1);

	
	stringstream s;

	for (int i=0; i<5 ;i++)
	{
		s.flush();
		s << i;
		if (TestUtils::VerifyIsTrue(noIntersection[i] == arrayA[i],"Did not clean matrix correctly at "+s.str()) != TestUtils::TestPassed)
		{
			return TestUtils::TestFailed;
		}
	}

	return TestUtils::TestPassed;
}

// check transposing and returning a matrix
	TestUtils::TestResult CheckTranspose()
{
/*	VERTEX_SIZE *ar = new VERTEX_SIZE[10];
	std::vector<bool> *cols;
	VERTEX_SIZE *expectedCols = new VERTEX_SIZE[4];
	VERTEX_SIZE *rows;
	

	for (int i = 1; i <= 10; i++)
	{
		ar[i-1] = i;		
	}

	Permutation perm(ar,4,10);

	cols = perm.GetMatrixColumns();
	rows = perm.GetMatrixRows();
	
	expectedCols[0] = bitset<10>(string("0000000111")).to_ulong();
	expectedCols[1] = bitset<10>(string("0001111000")).to_ulong();
	expectedCols[2] = bitset<10>(string("0110011001")).to_ulong();
	expectedCols[3] = bitset<10>(string("1010101010")).to_ulong();

	stringstream s;

	for (int i = 0; i < 4; i++)
	{
		s.flush();
		s << i;
		
		if (TestUtils::VerifyIsTrue(expectedCols[i]==cols[i],"expected cols and cols differ at "+ s.str()) == TestUtils::TestFailed)
		{
			return TestUtils::TestFailed;
		}
	}

	for (int i = 0; i < 10; i++)
	{
		s.flush();
		s << i;
		if (TestUtils::VerifyIsTrue(ar[i]==rows[i],"original matrix and rows differ at " +s.str()) == TestUtils::TestFailed)
		{
			return TestUtils::TestFailed;
		}
	}*/
	return TestUtils::TestPassed;
}


TestUtils::TestResult CheckTransposeNew()
{
	
	//the matrix we are chaking:
	//1001	9
	//0010	2
	//0001	1
	bool arr0[] = {1,0,0};
	bool arr1[] = {0,0,0};
	bool arr2[] = {0,1,0};
	bool arr3[] = {1,0,1};

	vector<bool> v0(arr0, arr0+3);
	vector<bool> v1(arr1, arr1+3);
	vector<bool> v2(arr2, arr2+3);
	vector<bool> v3(arr3, arr3+3);

	VERTEX_SIZE ar[] = {9, 2, 1};

	Permutation perm(ar, 4, 3);
	vector<bool> *vec = perm.GetMatrixColumns();

	for(int i=0; i < 3; i++)
	{
		if (TestUtils::VerifyIsTrue(v0[i] == (vec[0])[i],"coulmens and expected columns are differnt") == TestUtils::TestFailed)
		{
			return TestUtils::TestFailed;
		}
	}

	for(int i=0; i < 3; i++)
	{
		if (TestUtils::VerifyIsTrue(v1[i] == (vec[1])[i],"coulmens and expected columns are differnt") == TestUtils::TestFailed)
		{
			return TestUtils::TestFailed;
		}
	}

	for(int i=0; i < 3; i++)
	{
		if (TestUtils::VerifyIsTrue(v2[i] == (vec[2])[i],"coulmens and expected columns are differnt") == TestUtils::TestFailed)
		{
			return TestUtils::TestFailed;
		}
	}

	for(int i=0; i < 3; i++)
	{
		if (TestUtils::VerifyIsTrue(v3[i] == (vec[3])[i],"coulmens and expected columns are differnt") == TestUtils::TestFailed)
		{
			return TestUtils::TestFailed;
		}
	}

	return TestUtils::TestPassed;
}

TestUtils::TestResult CheckTransposeBack()
{
	//the matrix we are chaking:
	//1001	9
	//0010	2
	//0001	1
	
	bool arr0[] = {1,0,0};
	bool arr1[] = {0,0,0};
	bool arr2[] = {0,1,0};
	bool arr3[] = {1,0,1};

	vector<bool> v0(arr0, arr0+3);
	vector<bool> v1(arr1, arr1+3);
	vector<bool> v2(arr2, arr2+3);
	vector<bool> v3(arr3, arr3+3);

	vector<bool> columns[4];

	columns[0] = v0;
	columns[1] = v1;
	columns[2] = v2;
	columns[3] = v3;

	VERTEX_SIZE *rows = Permutation::TransposeColumnMatrixBit(columns, 4, 3); 

	if (TestUtils::VerifyIsTrue(rows[0] == 9,"rows and expected rows are differnt") == TestUtils::TestFailed)
	{
		return TestUtils::TestFailed;
	}

	if (TestUtils::VerifyIsTrue(rows[1] == 2,"rows and expected rows are differnt") == TestUtils::TestFailed)
	{
		return TestUtils::TestFailed;
	}


	if (TestUtils::VerifyIsTrue(rows[2] == 1,"rows and expected rows are differnt") == TestUtils::TestFailed)
	{
		return TestUtils::TestFailed;
	}

	return TestUtils::TestPassed;
}

TestUtils::TestResult CheckNextPermutaion()
{
#if 0
	VERTEX_SIZE *ar = new unsigned long[10];
	VERTEX_SIZE *cols;
	VERTEX_SIZE *expectedCols = new unsigned long[4];

	for (int i = 1; i <= 10; i++)
	{
		ar[i-1] = i;		
	}

	Permutation perm(ar,4,10);
	
	Permutation *newPerm = perm.NextPermutation();
	cols = newPerm->GetMatrixColumns();

	expectedCols[0] = bitset<10>(string("0000000111")).to_ulong();
	expectedCols[1] = bitset<10>(string("0001111000")).to_ulong();
	expectedCols[2] = bitset<10>(string("1010101010")).to_ulong();
	expectedCols[3] = bitset<10>(string("0110011001")).to_ulong();
	
	stringstream s;

	for (int i = 0; i < 4; i++)
	{
		s.flush();
		s << i;
		
		if (TestUtils::VerifyIsTrue(expectedCols[i]==cols[i],"expected cols and cols differ at "+ s.str()) == TestUtils::TestFailed)
		{
			delete[] expectedCols;
			delete cols;
			delete newPerm;
			return TestUtils::TestFailed;
		}
	}

	delete[] expectedCols;
	delete cols;
	delete newPerm;
	return TestUtils::TestPassed;
#endif
	Debug::PrintDebugMsg("CheckNextPermutaion - irrelevent test");
	return TestUtils::TestPassed;
}


// check removing intersection from a chain
TestUtils ::TestResult CheckRemoveIntersections()
{
	VERTEX_SIZE arrayA[6] = {13,54,555,100000000,16,77};
	VERTEX_SIZE arrayB[6] = {10,43,90,77}; // intersection with A - 1
	VERTEX_SIZE arrayC[6] = {10,44,95,77,27};// intersection with A - 1, intersection with B - 1

	VERTEX_SIZE expectedArrayA[6] = {13,54,555,100000000,16,77};
	VERTEX_SIZE expectedArrayB[6] = {10,43,90,77};
	VERTEX_SIZE expectedArrayC[6] = {10,44,95,16,27};
	//simple intersection: 1
	Permutation* per1 = new Permutation(arrayA,32,6);
	Permutation* per2 = new Permutation(arrayB,32,4);
	Permutation* per3 = new Permutation(arrayC,32,5);

	Permutation* expectedPer1 = new Permutation(expectedArrayA,32,6);
	Permutation* expectedPer2 = new Permutation(expectedArrayB,32,4);
	Permutation* expectedPer3 = new Permutation(expectedArrayC,32,5);

	int intersectionAB = per1->CountIntersection(expectedArrayB,4);
	int intersectionAC = per1->CountIntersection(expectedArrayC,5);
	int intersectionBC = per2->CountIntersection(expectedArrayC,5);

	Chain chain(17);
	chain.PushPermutation(per1);
	chain.PushPermutation(per2);
	chain.PushPermutation(per3);
	chain.RemoveIntersections();
	
	// expected result - per1 unchanged, per2, per3 are missing the intersection
	// intersection AB removed from B, intersection AC removed from C, intersection BC removed from B

	stringstream s;
	s.flush();
	
	Permutation* thirdPerm = chain.PopPermutation();
	s << thirdPerm->GetGroupSize();
	if (TestUtils::VerifyIsTrue(thirdPerm->GetGroupSize() == expectedPer3->GetGroupSize()-intersectionAC ,"Actual group size after intersection (group C) "+s.str()) != TestUtils::TestPassed)
	{
		return TestUtils::TestFailed;
	}

	VERTEX_SIZE *noIntersection = Permutation::GetMatrixWithoutIntersection(expectedArrayC, 5, expectedArrayA, 6,intersectionAC);
	
	for (int i=0; i<expectedPer3->GetGroupSize()-intersectionAC ;i++)
	{
		s.flush();
		s << i;
		if (TestUtils::VerifyIsTrue(thirdPerm->GetMatrixRows()[i]==noIntersection[i],"Did not clean matrix correctly at "+s.str()) != TestUtils::TestPassed)
		{
			return TestUtils::TestFailed;
		}
	}


	Permutation* secondPerm = chain.PopPermutation();
	s.flush();
	s << secondPerm->GetGroupSize();
	if (TestUtils::VerifyIsTrue(secondPerm->GetGroupSize() == expectedPer2->GetGroupSize()-intersectionAB-intersectionBC ,"Actual group size after intersection (group B) "+s.str()) != TestUtils::TestPassed)
	{
		return TestUtils::TestFailed;
	}

	noIntersection = Permutation::GetMatrixWithoutIntersection(expectedArrayB, 4, expectedArrayA, 6,intersectionAB);
	noIntersection = Permutation::GetMatrixWithoutIntersection(noIntersection, 3, arrayC, 4,intersectionBC); // array C - without A!

	for (int i=0; i<expectedPer2->GetGroupSize()-intersectionAB-intersectionBC ;i++)
	{
		s.flush();
		s <<i;
		if (TestUtils::VerifyIsTrue(secondPerm->GetMatrixRows()[i]==noIntersection[i],"Did not clean matrix correctly at "+s.str()) != TestUtils::TestPassed)
		{
			return TestUtils::TestFailed;
		}
	}

	Permutation *firstPerm = chain.PopPermutation();
	s.flush();
	s.flush();
	s << firstPerm->GetGroupSize();
	if (TestUtils::VerifyIsTrue(firstPerm->GetGroupSize() == expectedPer1->GetGroupSize() ,"Actual group size after intersection (group A) "+s.str()) != TestUtils::TestPassed)
	{
		return TestUtils::TestFailed;
	}

	for (int i=0; i<expectedPer1->GetGroupSize() ;i++)
	{
		s.flush();
		s << i;
		if (TestUtils::VerifyIsTrue(firstPerm->GetMatrixRows()[i] == expectedArrayA[i],"Did not clean matrix correctly at "+s.str()) != TestUtils::TestPassed)
		{
			return TestUtils::TestFailed;
		}
	}

	return TestUtils::TestPassed;
}

// check Chain::IsLegalToAdd 
TestUtils::TestResult CheckAddToChain()
{
	VERTEX_SIZE arrayA[6] = {13,54,555,100000000,16,77};
	VERTEX_SIZE arrayB[6] = {10,43,90,77,78}; // intersection with A - 1
	
	Permutation* per1 = new Permutation(arrayA,32,6,1);
	Permutation* per2 = new Permutation(arrayB,32,5,2);
		
	Chain chain(2);
	if (TestUtils::VerifyIsTrue(chain.IsLegalToAdd(per1),"Could not add permutation to empty chain") != TestUtils::TestPassed)
	{
		return TestUtils::TestFailed;
	}
	chain.PushPermutation(per1);
	if (TestUtils::VerifyIsTrue(chain.IsLegalToAdd(per2),"Could not add permutation2 to chain with 1 perm") != TestUtils::TestPassed)
	{
		return TestUtils::TestFailed;
	}
	chain.PushPermutation(per2);

	if (TestUtils::VerifyIsTrue(!(chain.IsLegalToAdd(per2)),"Could add same permutation to chain!") != TestUtils::TestPassed)
	{
		return TestUtils::TestFailed;
	}

	return TestUtils::TestPassed;
}


TestUtils::TestResult CheckPermutationsFill()
{
	int wordLen = 3; int wordWeight = 2;  int groupSize = 2; 
	int maxIntersection = 1; int minChainLength = 1; 
	int maxChains = 5000; int permutationPercent = 100;

	VERTEX_SIZE originalPerm[2] = {3,5};
	Permutations perms(originalPerm,wordLen, wordWeight ,groupSize,maxIntersection,minChainLength, maxChains, permutationPercent);
	perms.Fill();

	// Expected permutations:
	// original perm:
	// 1: (123) 011,101 (index 1, related 2)
	// other perms:
	// 2: (132) 011,110 (index 2, related 1)
	// 3: (213) 101,011 NOT SAVED (identical to original)
	// 4: (231) 110,011 NOT SAVED (identical to perm2)
	// 5: (312) 101,110 NOT SAVED (is identical to perm2 after removing intersection with original)
	// 6: (321) 110,101 NOT SAVED  (is idenctical to perm5)
	int expectedPermutationsNumber = 2;
	vector<Permutation*> expectedPerms;
	VERTEX_SIZE perm2[2] = {6};
		
	expectedPerms.push_back(new Permutation(originalPerm,wordLen,groupSize,1));
	expectedPerms.push_back(new Permutation(perm2,wordLen,groupSize-1,2));
		
	expectedPerms[0]->AddRelatedPerm(RelatedPermutation(expectedPerms[1]->GetName(),1, expectedPerms[1]->GetGroupSize()));
	expectedPerms[1]->AddRelatedPerm(RelatedPermutation(expectedPerms[0]->GetName(),1, expectedPerms[0]->GetGroupSize()));
	
	// Now compare
	vector<Permutation> actualPermList = perms.GetPermutations();
	if (TestUtils::VerifyIsTrue(actualPermList.size() == expectedPermutationsNumber, "Unexpected number of permutations after fill") != TestUtils::TestPassed)
	{
		for (int i=0; i<expectedPermutationsNumber; i++)
		{
			delete expectedPerms[i];
		}
		return TestUtils::TestFailed;
	}

	for (int i=0; i<expectedPermutationsNumber; i++)
	{
		Permutation actualPerm = actualPermList[i];
		Permutation expectedPerm = *(expectedPerms[i]);

		if (TestUtils::VerifyIsTrue(actualPerm == expectedPerm, "Permutations are not equal!")!=TestUtils::TestPassed)
		{

			for (int i=0; i<expectedPermutationsNumber; i++)
			{	
				delete expectedPerms[i];
			}
			return TestUtils::TestFailed;
		}

		if (VerifyRelatedPermutationsAreSame(actualPerm,expectedPerm)!=TestUtils::TestPassed)
		{
			for (int i=0; i<expectedPermutationsNumber; i++)
			{
				delete expectedPerms[i];
			}
			return TestUtils::TestFailed;
		}
	}

	for (int i=0; i<expectedPermutationsNumber; i++)
	{
		delete expectedPerms[i];
	}

	perms.CreateAllChains("testing-CheckPermutationsFill");

	return TestUtils::TestPassed;
}

// Helper function to compare 2 related permutation lists
TestUtils::TestResult VerifyRelatedPermutationsAreSame(Permutation &perm1, Permutation &perm2)
{

	if (TestUtils::VerifyIsTrue(perm1.GetRelatedPermsCount() == perm2.GetRelatedPermsCount(), "Permutations do not have same number of related perms")!= TestUtils::TestPassed)
	{
		return TestUtils::TestFailed;
	}
	
	vector<RelatedPermutation>::iterator it1, it2;
	for (it1=perm1.GetRelatedPermsBegin(); it1 != perm1.GetRelatedPermsEnd(); it1++)
	{
		bool found = false;
		// go over 2nd list and see if permutation is found
		for (it2 = perm2.GetRelatedPermsBegin(); it2 != perm2.GetRelatedPermsEnd() && !found; it2++)
		{
			if ((*it1)==(*it2))
			{
				found = true;
			}
		}
		
		// If perm still wasn't found - not equal
		if (TestUtils::VerifyIsTrue(found, "Permutation appears in perm1 and not 2")!=TestUtils::TestPassed)
		{
			return TestUtils::TestFailed;
		}
	}

	return TestUtils::TestPassed;
}	


TestUtils::TestResult CheckPermutationsChains()
{
	int wordLen = 3; int wordWeight = 2; int groupSize = 3; int maxIntersection = 1; 
	int minChainLength = 2; int maxChains = 3; int permutationPercent = 100;
	VERTEX_SIZE originalPerm[3] = {1,3,4};
	Permutations perms(originalPerm,wordLen,wordWeight,groupSize,maxIntersection, minChainLength, maxChains, permutationPercent);
	perms.Fill();
	perms.CreateAllChains("testing-CheckPermutationsChains");

	// Original permutation:
	//(126) - related 2,3
	//001 = 1
	//011 = 3
	//100 = 4
	//
	//Others:
	//(162)  (NOT SAVED)
	//010 = 2
	//011 = 3
	//100 = 4 
	//
	//(216) related: 3, index 2
	//001 = 1
	//101 = 5
	//010 = 2
	//
	//(261) - related : none, index 3
	//010 = 2
	//110 = 6
	//001 = 1
	//
	//(612) (NOT SAVED)
	//100 = 1
	//101 = 5
	//010 = 2
	//
	//(621) (NOT SAVED)
	//100 = 4
	//110 = 3
	//001 = 1
	
	ifstream actualChainFile;
	ifstream expectedChainFile;
	string actualFileStr;
	string expectedFileStr;
	string line;

	//first chain check:
	actualChainFile.open("testing-CheckPermutationsChains_chain1.chain");
	while (getline(actualChainFile,line))
	{
		actualFileStr.append(line);
	}
	actualChainFile.close();

	expectedChainFile.open("testingExpectedChain1.chain");
	while (getline(expectedChainFile,line))
	{
		expectedFileStr.append(line);
	}
	expectedChainFile.close();

	// if perm still wasn't found - not equal
	if (TestUtils::VerifyIsTrue(actualFileStr==expectedFileStr, "chain 1 output is not as expected")!=TestUtils::TestPassed)
	{
		return TestUtils::TestFailed;
	}

	//second chain check:
	actualChainFile.open("testing-CheckPermutationsChains_chain2.chain");
	while (getline(actualChainFile,line))
	{
		actualFileStr.append(line);
	}
	actualChainFile.close();

	expectedChainFile.open("testingExpectedChain2.chain");
	while (getline(expectedChainFile,line))
	{
		expectedFileStr.append(line);
	}
	expectedChainFile.close();

	// if perm still wasn't found - not equal
	if (TestUtils::VerifyIsTrue(actualFileStr==expectedFileStr, "chain 2 output is not as expected")!=TestUtils::TestPassed)
	{
		return TestUtils::TestFailed;
	}

	//third chain check:
	actualChainFile.open("testing-CheckPermutationsChains_chain3.chain");
	while (getline(actualChainFile,line))
	{
		actualFileStr.append(line);
	}
	actualChainFile.close();

	expectedChainFile.open("testingExpectedChain3.chain");
	while (getline(expectedChainFile,line))
	{
		expectedFileStr.append(line);
	}
	expectedChainFile.close();

	// if perm still wasn't found - not equal
	if (TestUtils::VerifyIsTrue(actualFileStr==expectedFileStr, "chain 3 output is not as expected")!=TestUtils::TestPassed)
	{
		return TestUtils::TestFailed;
	}

	return TestUtils::TestPassed;
}

TestUtils::TestResult CheckLoad()
{
#if 0
	CMarkup xml;
	ChainParser chainFile;
	InputParmetersParser inputFile;

	int expectedN = 14;
	int expectedSize = 1;
	int expectedMaxIntersection = 3;
	int expectedMaxChains = 40;
	int expectedMinLength = 10;
	int expectedVertex = 6;

	xml.AddElem(MULTIPLE_CHAINS_XML);
	Permutations *perms;
	perms = Permutations::CreatePermutationsObject(chainFile, inputFile);

	if (TestUtils::VerifyIsTrue(perms==NULL, "Created permutations object without general part")!=TestUtils::TestPassed)
	{
		return TestUtils::TestFailed;
	}
	
	xml.AddElem(INPUT_XML_GENERAL);
	xml.ResetPos();
	perms = Permutations::CreatePermutationsObject(xml);

	if (TestUtils::VerifyIsTrue(perms==NULL, "Created permutations object without n")!=TestUtils::TestPassed)
	{
		return TestUtils::TestFailed;
	}
	xml.ResetPos();
	xml.FindElem(); xml.IntoElem();	
	xml.FindElem(INPUT_XML_GENERAL);
	xml.IntoElem();
	xml.AddElem(INPUT_XML_N,expectedN);
	xml.ResetPos();
	perms = Permutations::CreatePermutationsObject(xml);

	if (TestUtils::VerifyIsTrue(perms==NULL, "Created permutations object without permutations")!=TestUtils::TestPassed)
	{
		return TestUtils::TestFailed;
	}

	xml.ResetPos();
	xml.FindElem(); xml.IntoElem();	
	xml.AddElem(INPUT_XML_PERMUTATIONS);
    xml.ResetPos();
	perms = Permutations::CreatePermutationsObject(xml);
	if (TestUtils::VerifyIsTrue(perms==NULL, "Created permutations object without initial group")!=TestUtils::TestPassed)
	{
		return TestUtils::TestFailed;
	}

	xml.ResetPos();
	xml.FindElem(); xml.IntoElem();	
	xml.FindElem(INPUT_XML_PERMUTATIONS);
	xml.IntoElem();
	xml.AddElem(INPUT_XML_INITIAL_GROUP);
	xml.IntoElem();
	xml.AddElem(VERTEX_XML,"0110"); // expected vertex
	xml.ResetPos();
	perms = Permutations::CreatePermutationsObject(xml);

	if (TestUtils::VerifyIsTrue(perms==NULL, "Created permutations object without minimum chain length")!=TestUtils::TestPassed)
	{
		return TestUtils::TestFailed;
	}

	xml.ResetPos();
	xml.FindElem(); xml.IntoElem();	
	xml.FindElem(INPUT_XML_PERMUTATIONS);
	xml.IntoElem();
	xml.AddElem(INPUT_XML_MIN_CHAIN_LEN,expectedMinLength);
	xml.ResetPos();
	perms = Permutations::CreatePermutationsObject(xml);

	if (TestUtils::VerifyIsTrue(perms==NULL, "Created permutations object without max intersection")!=TestUtils::TestPassed)
	{
		return TestUtils::TestFailed;
	}

	xml.ResetPos();
	xml.FindElem(); xml.IntoElem();	
	xml.FindElem(INPUT_XML_PERMUTATIONS);
	xml.IntoElem();
	xml.AddElem(INPUT_XML_MAX_INTERSECTION_SIZE,expectedMaxIntersection);
	xml.ResetPos();
	perms = Permutations::CreatePermutationsObject(xml);

	if (TestUtils::VerifyIsTrue(perms==NULL, "Created permutations object without max chains")!=TestUtils::TestPassed)
	{
		return TestUtils::TestFailed;
	}

	xml.ResetPos();
	xml.FindElem(); xml.IntoElem();	
	xml.FindElem(INPUT_XML_PERMUTATIONS);
	xml.IntoElem();
	xml.AddElem(INPUT_XML_MAX_CHAINS,expectedMaxChains);
	xml.ResetPos();
	perms = Permutations::CreatePermutationsObject(xml);

	if (TestUtils::VerifyIsTrue(perms!=NULL, "Failed to create object from XML")!=TestUtils::TestPassed)
	{
		return TestUtils::TestFailed;
	}

	// Now verify details
	if (TestUtils::VerifyIsTrue(perms->GetGroupSize()==expectedSize, "Wrong number of vertices")!=TestUtils::TestPassed)
	{
		return TestUtils::TestFailed;
	}
	if (TestUtils::VerifyIsTrue(perms->GetMaxChains()==expectedMaxChains, "Wrong max chains")!=TestUtils::TestPassed)
	{
		return TestUtils::TestFailed;
	}
	if (TestUtils::VerifyIsTrue(perms->GetMaxIntersection()==expectedMaxIntersection, "Wrong max intersection")!=TestUtils::TestPassed)
	{
		return TestUtils::TestFailed;
	}
	if (TestUtils::VerifyIsTrue(perms->GetMinChainLength()==expectedMinLength, "Wrong minimum chain length")!=TestUtils::TestPassed)
	{
		return TestUtils::TestFailed;
	}
	if (TestUtils::VerifyIsTrue(perms->GetOriginalPermutation()->GetMatrixRows()[0]==expectedVertex, "Wrong vertex")!=TestUtils::TestPassed)
	{
		return TestUtils::TestFailed;
	}
#endif
	return TestUtils::TestPassed;

}

void RunTests()
{
	// check the intersection between 2 simple permutations arrays
	TestUtils::PrintTestResult("Check intersection (1)", CheckIntersection1());

	// check the intersection between 2 permutations arrays
	TestUtils::PrintTestResult("Check intersection (2)", CheckIntersection2());

	// Check transposing a bit matrix
	//TestUtils::PrintTestResult("Check transpose", CheckTranspose());

	// Check removing intersections from chain
	TestUtils::PrintTestResult("Test remove intersections from chain", CheckRemoveIntersections());

	// check next permutaion
	TestUtils::PrintTestResult("Test that next permutaion works corectly", CheckNextPermutaion());
	
	// Check IsLegalToAdd for chain
	TestUtils::PrintTestResult("Test IsLegalToAdd to chain", CheckAddToChain());

	// Check Fill
	TestUtils::PrintTestResult("Test Permutations fill", CheckPermutationsFill());

	// Check Create chains
	TestUtils::PrintTestResult("Test Permutations chains", CheckPermutationsChains());

	// Check load
	TestUtils::PrintTestResult("Test loading from xml", CheckLoad());

	//check transpose (new)
	TestUtils::PrintTestResult("check transpose (new)", CheckTransposeNew());

	//check transpose back
	TestUtils::PrintTestResult("check transpose back", CheckTransposeBack());

}